package edu.wpi.cs509.ui.intfc;

import edu.wpi.cs509.common.exceptions.*;
import edu.wpi.cs509.representation.Location;
import edu.wpi.cs509.representation.PlayerPiece;
import edu.wpi.cs509.representation.TeamColor;

/**
 * This interface defines the methods that the Stratego UI will
 * invoke in the Client Logic to fulfill game requests made by the user.
 * 
 * @author afoltan
 *
 */
public interface GameInterface {
	
	/**
	 * This method is used during initial piece placement by the user to setup their
	 * side of the playing board.
	 * 
	 * Response:
	 * 		notifyPieceMoved
	 * 
	 * @param loc - the destination board square
	 * @param piece - the stratego piece to place
	 * @throws IllegalMove - if the piece cannot be legally placed on the indicated square
	 * @throws InvalidLocation - if the location is out of bounds
	 * @throws ServerUnreachable - if the game server could not be reached
	 */
	void placePiece( Location loc, PlayerPiece piece ) throws IllegalMove, InvalidLocation, ServerUnreachable;
	
	/**
	 * This method is used during initial piece placement by the user to setup their
	 * side of the playing board.
	 * 
	 * Response:
	 * 		notifyPieceRemoved
	 * 
	 * @param loc - the destination board square
	 * @param piece - the stratego piece to place
	 * @throws IllegalMove - if the piece cannot be legally placed on the indicated square
	 * @throws InvalidLocation - if the location is out of bounds
	 * @throws ServerUnreachable - if the game server could not be reached
	 */
	void removePiece( Location loc) throws IllegalMove, InvalidLocation, ServerUnreachable;
	
	/**
	 * Indicates the player has completed their initial placement.  The server will
	 * wait for the opponent to also indicate 'ready' before it responds.
	 * 
	 * Response:
	 * 		notifyGameStarted
	 * 
	 * @throws InitialPlacementError - indicates that the initial placement of pieces is not complete
	 * @throws ServerUnreachable - if the game server could not be reached
	 */
	void ready() throws InitialPlacementError, ServerUnreachable;
	
	/**
	 * Move is called to initiate the movement of a player's game piece.
	 * 
	 * Response:
	 * 		notifyPieceMoved
	 * 		notifyAttack
	 * 
	 * @param from - the originating game square
	 * @param to - the destination game square
	 * @throws IllegalMove - indicates that the move is not legal
	 * @throws ServerUnreachable - if the game server could not be reached
	 */
	void move( Location from, Location to ) throws IllegalMove, ServerUnreachable;

	/**
	 * Ends a game for the user/game specified.
	 * 
	 * Response:
	 * 		notifyGameOver
	 * 
	 * @throws ServerUnreachable - if the game server could not be reached
	 */
	void quit() throws ServerUnreachable;

	
	//
	//   Methods for accessing the GAME object
	// 
	
	/**
	 * Indicates the specified board square has no piece on it
	 * 
	 * @param loc - the board square
	 * @return - true if square is empty, false otherwise
	 */
	boolean isSquareEmpty( Location loc ) throws InvalidLocation;
	
	/**
	 * Returns the piece at the board location specified
	 * 
	 * @param loc - the board square
	 * @return - the PlayerPiece on that square
	 */
	PlayerPiece getPiece( Location loc ) throws PieceNotFound;
	
	/**
	 * Returns the unique game ID for this game
	 * @return
	 */
	long getGameID();
	
	/**
	 * Returns my username for display
	 * 
	 * @note Implementations must never return null from this method
	 * 
	 * @return
	 */
	String getMyName();

	/**
	 * Returns my opponent's username for display
	 * 
	 * @note Implementations may return null from this method, in which case
	 * the UI will display a "Waiting for Player..." message
	 * 
	 * @return
	 */
	String getOpponentName();
	
	/**
	 * Returns the color of my side (for active games), or the 
	 * color of the side at the bottom of the screen for 
	 * observed games.
	 * 
	 * @note Implementations must never return null from this method

	 * @return
	 */
	TeamColor getMyColor();

	/**
	 * Returns the color of my opponent (for active games), or
	 * the color of the side at the top of the screen for
	 * observed games.
	 * 
	 * @note Implementations must never return null from this method
	 * 
	 * @return
	 */
	TeamColor getOpponentColor();

	/**
	 * Indicates this game is joinable (no player 2 yet)
	 * 
	 * @return true if joinable, false otherwise
	 */
	boolean isJoinable();

	/**
	 * Indicates whether this game is being observed
	 * 
	 * @return true is this is an observed game, false if this game
	 * is the active game
	 */
	boolean isObservable();

	/**
	 * Indicates the opponent pieces should remain hidden
	 * @return
	 */
	boolean obfuscatePieces();
	
	/**
	 * Indicates the game is only observable
	 * @return
	 */
	boolean gameIsObserver();
	
}

